
#ifndef  _RADIX_ARCHAISM_MATH_H_
#define  _RADIX_ARCHAISM_MATH_H_

#include <Archaism/Header.h>

_BeginNamespace(Radix)
/*
============================================================
== Vector2
============================================================
*/
class Vector2
{
public:
	Vector2();
	Vector2(real x, real y);
	Vector2(const real (&v)[2]);
	Vector2(const Vector2& v);
	~Vector2();

public:
	Vector2& operator=(const Vector2& v);
	Vector2 operator-();

	Vector2 operator+(const Vector2& v);
	Vector2 operator-(const Vector2& v);
	Vector2 operator*(const Vector2& v);
	Vector2 operator*(real t);
	Vector2 operator/(const Vector2& v);
	Vector2 operator/(real t);

	Vector2& operator+=(const Vector2& v);
	Vector2& operator-=(const Vector2& v);
	Vector2& operator*=(const Vector2& v);
	Vector2& operator*=(real t);

	bool operator==(const Vector2& v);
	bool operator!=(const Vector2& v);

public:
	real length();
	Vector2& normalize();

public:
	real x;
	real y;
};
/*
============================================================
== Vector3
============================================================
*/
class Vector3
{
public:
	Vector3();
	Vector3(real x, real y, real z);
	Vector3(const real (&v)[3]);
	Vector3(const Vector2& v);
	Vector3(const Vector3& v);
	~Vector3();

public:
	Vector3& operator=(const Vector3& v);
	Vector3 operator-();

	Vector3 operator+(const Vector3& v);
	Vector3 operator-(const Vector3& v);
	Vector3 operator*(const Vector3& v);
	Vector3 operator*(real t);

	Vector3& operator+=(const Vector3& v);
	Vector3& operator-=(const Vector3& v);
	Vector3& operator*=(const Vector3& v);
	Vector3& operator*=(real t);

	bool operator==(const Vector3& v);
	bool operator!=(const Vector3& v);

public:
	real length();
	Vector3& normalize();

public:
	real x;
	real y;
	real z;
};
/*
============================================================
== Vector4
============================================================
*/
class Vector4
{
public:
	Vector4();
	Vector4(real x, real y, real z, real w = 1);
	Vector4(const real (&v)[4]);
	Vector4(const Vector3& v);
	Vector4(const Vector4& v);
	~Vector4();

public:
	Vector4& operator=(const Vector4& v);
	Vector4 operator-();

	Vector4 operator+(const Vector4& v);
	Vector4 operator-(const Vector4& v);
	Vector4 operator*(const Vector4& v);
	Vector4 operator*(real t);

	Vector4& operator+=(const Vector4& v);
	Vector4& operator-=(const Vector4& v);
	Vector4& operator*=(const Vector4& v);
	Vector4& operator*=(real t);

	bool operator==(const Vector4& v);
	bool operator!=(const Vector4& v);

public:
	real x;
	real y;
	real z;
	real w;
};

/*
============================================================
== Matrix3x3
============================================================
*/
class Matrix3x3
{
public:
	Matrix3x3();
	Matrix3x3(const real (&m)[3][3]);
	Matrix3x3(const Matrix3x3& m);
	~Matrix3x3();

public:
	Matrix3x3& operator=(const Matrix3x3& m);
	Matrix3x3 operator-();

	Matrix3x3 operator+(const Matrix3x3& m);
	Matrix3x3 operator-(const Matrix3x3& m);
	Matrix3x3 operator*(const Matrix3x3& m);

	Matrix3x3& operator+=(const Matrix3x3& m);
	Matrix3x3& operator-=(const Matrix3x3& m);
	Matrix3x3& operator*=(const Matrix3x3& m);

	bool operator==(const Matrix3x3& m);
	bool operator!=(const Matrix3x3& m);

public:
	Matrix3x3& identity();
	Matrix3x3& transpose();

public:
	real value[3][3];
};

/*
============================================================
== Matrix4x4
============================================================
*/
class Matrix4x4
{
public:
	Matrix4x4();
	Matrix4x4(const real (&m)[4][4]);
	Matrix4x4(const Matrix4x4& m);
	Matrix4x4(const Matrix3x3& m);
	~Matrix4x4();

public:
	Matrix4x4& operator=(const Matrix4x4& m);
	Matrix4x4 operator-();

	Matrix4x4 operator+(const Matrix4x4& m);
	Matrix4x4 operator-(const Matrix4x4& m);
	Matrix4x4 operator*(const Matrix4x4& m);

	Matrix4x4& operator+=(const Matrix4x4& m);
	Matrix4x4& operator-=(const Matrix4x4& m);
	Matrix4x4& operator*=(const Matrix4x4& m);

	bool operator==(const Matrix4x4& m);
	bool operator!=(const Matrix4x4& m);

	Matrix4x4& identity();
	Matrix4x4& transpose();

public:
	real value[4][4];
};

/*
============================================================
== Quaternion
============================================================
*/
class Quaternion
{
public:
	Quaternion();
	Quaternion(real x, real y, real z, real w = 1);
	Quaternion(const real (&q)[4]);
	Quaternion(const Quaternion& q);
	~Quaternion();

public:
	Quaternion& operator=(const Quaternion& m);
	Quaternion operator-();

	Quaternion operator+(const Quaternion& m);
	Quaternion operator-(const Quaternion& m);
	Quaternion operator*(const Quaternion& m);

	Quaternion& operator+=(const Quaternion& m);
	Quaternion& operator-=(const Quaternion& m);
	Quaternion& operator*=(const Quaternion& m);

	bool operator==(const Quaternion& m);
	bool operator!=(const Quaternion& m);

public:
	real x;
	real y;
	real z;
	real w;
};

/*
============================================================
== Ray
============================================================
*/
class Ray
{
public:
	Ray();
	Ray(const Vector3& origin, const Vector3& direction);
	Ray(const Ray& ray);
	~Ray();

public:
	Vector3 getPoint(real t);

public:
	Vector3 mOrigin;
	Vector3 mDirection;
};
/*
============================================================
== Math
============================================================
*/
class Math
{
public:
	static const real mskEpsilon4;
	static const real mskEpsilon5;
	static const real mskEpsilon6;
	static const real mskPi;

public:
	static real degreeToRadian(real degree);
	static real radianToDegree(real radian);

	static real clamp(real x, real min, real max);
	static real saturate(real x);

public:
	static real dot(const Vector2& v1, const Vector2& v2);
	static real dot(const Vector3& v1, const Vector3& v2);
	static real dot(const Vector4& v1, const Vector4& v2);
	static Vector3 cross(const Vector3& v1, const Vector3& v2);

public:
	static void transform(Vector3& result, const Vector3& v, const Matrix3x3& m);
	static void transform(Vector4& result, const Vector4& v, const Matrix4x4& m);
	static void transform(Matrix3x3& result, const Matrix3x3& m1, const Matrix3x3& m2);
	static void transform(Matrix4x4& result, const Matrix4x4& m1, const Matrix3x3& m2);

public:
	static Matrix3x3 matrixTranslation(const Vector2& dir);
	static Matrix4x4 matrixTranslation(const Vector3& dir);
	static Matrix3x3 matrixRotation(const Vector2& axis, real angle);
	static Matrix4x4 matrixRotation(const Vector3& axis, real angle);
	static Matrix3x3 matrixScaling(const Vector2& scale);
	static Matrix4x4 matrixScaling(const Vector3& scale);
};

_EndNamespace(Radix)

#endif//_RADIX_ARCHAISM_MATH_H_
